home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / Utilities / LinkList.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  15.0 KB  |  623 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        LinkList.cpp
  3.  
  4.     Contains:    Linked-list class w/iterator
  5.  
  6.     Owned by:    Reggie Adkins
  7.  
  8.     Copyright:    © 1993-96 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <3>     5/24/96    jpa        Fixed header comment.
  13.          <2>     5/24/96    jpa        1339104: Inlined methods for efficiency
  14.                                     (EditorSetup)
  15.  
  16.     To Do:
  17. */
  18.  
  19. #ifndef _LINKLIST_
  20. #include "LinkList.h"
  21. #endif
  22.  
  23. #ifndef _EXCEPT_
  24. #include "Except.h"
  25. #endif
  26.  
  27. #ifndef __ERRORS__
  28. #include <Errors.h>
  29. #endif
  30.  
  31. #ifndef _ODDEBUG_
  32. #include "ODDebug.h"
  33. #endif
  34.  
  35. #ifndef _UTILERRS_
  36. #include "UtilErrs.h"
  37. #endif
  38.  
  39. #pragma segment ODLinkedList
  40.  
  41. //==============================================================================
  42. // Constants
  43. //==============================================================================
  44.  
  45. //==============================================================================
  46. // Scalar Types
  47. //==============================================================================
  48.  
  49. //==============================================================================
  50. // Local Classes
  51. //==============================================================================
  52.  
  53. //==============================================================================
  54. // Global Variables
  55. //==============================================================================
  56.  
  57. //==============================================================================
  58. // Function Prototype
  59. //==============================================================================
  60.  
  61.  
  62. //==============================================================================
  63. // Link
  64. //==============================================================================
  65.  
  66.  
  67.  
  68. // Many of the simple link methods are inlines; see List.h for implementations.
  69.  
  70.  
  71. //------------------------------------------------------------------------------
  72. // Link::Link
  73. //
  74. // Constructor for Link
  75. //------------------------------------------------------------------------------
  76.  
  77. Link::Link()                            
  78.     fNext = kODNULL; 
  79.     fPrevious = kODNULL;
  80. }
  81.  
  82. //------------------------------------------------------------------------------
  83. // Link::Link
  84. //
  85. // Constructor for Link
  86. //------------------------------------------------------------------------------
  87.  
  88. Link::Link(Link* next, Link* previous)                            
  89.     fNext = next; 
  90.     fPrevious = previous;
  91. }
  92.  
  93. //------------------------------------------------------------------------------
  94. // Link::Link
  95. //
  96. // Copy constructor for Link
  97. //------------------------------------------------------------------------------
  98.  
  99. Link::Link( const Link &link )                            
  100.     fNext = link.fNext; 
  101.     fPrevious = link.fPrevious;
  102. }
  103.  
  104. //------------------------------------------------------------------------------
  105. // Link::Link
  106. //
  107. // Destructor for Link
  108. //------------------------------------------------------------------------------
  109.  
  110. Link::~Link()                                            
  111. {
  112. }
  113.  
  114. //------------------------------------------------------------------------------
  115. // Link::Remove
  116. //
  117. // Remove a link from its list (if any). DO NOT call this directly if there are
  118. // any iterators active on the list; use LinkedList::Remove instead.
  119. //------------------------------------------------------------------------------
  120.  
  121. void    Link::Remove( )
  122. {
  123.     if( fPrevious )
  124.         fPrevious->SetNext(fNext);
  125.     if( fNext )
  126.         fNext->SetPrevious(fPrevious);
  127.     fNext = kODNULL;
  128.     fPrevious = kODNULL;
  129. }
  130.  
  131. //------------------------------------------------------------------------------
  132. // Link::AddBefore
  133. //
  134. // Add a link to a list before another link. It must not already be on any list.
  135. // DO NOT call this directly if there are any iterators active on the list;
  136. // use LinkedList::Remove instead.
  137. //------------------------------------------------------------------------------
  138.  
  139. void    Link::AddBefore( Link *link )
  140. {
  141.     ASSERT(link!=kODNULL,paramErr);
  142.     WASSERT(fNext==kODNULL);
  143.     WASSERT(fPrevious==kODNULL);
  144.     fNext = link;
  145.     fPrevious = link->GetPrevious();
  146.     fPrevious->SetNext(this);
  147.     fNext->SetPrevious(this);
  148. }
  149.  
  150. //------------------------------------------------------------------------------
  151. // Link::AddAfter
  152. //
  153. // Add a link to a list after another link. It must not already be on any list.
  154. // DO NOT call this directly if there are any iterators active on the list;
  155. // use LinkedList::Remove instead.
  156. //------------------------------------------------------------------------------
  157.  
  158. void    Link::AddAfter( Link *link )
  159. {
  160.     ASSERT(link!=kODNULL,paramErr);
  161.     WASSERT(fNext==kODNULL);
  162.     WASSERT(fPrevious==kODNULL);
  163.     fPrevious = link;
  164.     fNext = link->GetNext();
  165.     fPrevious->SetNext(this);
  166.     fNext->SetPrevious(this);
  167. }
  168.  
  169. //======================================================================================
  170. // Class LinkedList
  171. //======================================================================================
  172.  
  173. //------------------------------------------------------------------------------
  174. // LinkedList::LinkedList
  175. //
  176. // Constructor for LinkedList
  177. //------------------------------------------------------------------------------
  178.  
  179. LinkedList::LinkedList()
  180.     :fSentinel(&fSentinel,&fSentinel),
  181.      fSeed(0)
  182. {
  183. }
  184.  
  185. //------------------------------------------------------------------------------
  186. // LinkedList::IsEmpty
  187. //
  188. // Description
  189. //------------------------------------------------------------------------------
  190.  
  191. ODBoolean LinkedList::IsEmpty() const
  192. {
  193.     return this->IsSentinel( fSentinel.GetNext() );
  194. }
  195.  
  196. //------------------------------------------------------------------------------
  197. // LinkedList::Count
  198. //
  199. // Description
  200. //------------------------------------------------------------------------------
  201.  
  202. ODULong LinkedList::Count() const
  203. {
  204.     Link* l = fSentinel.GetNext();
  205.     ODULong count = 0;
  206.     while (this->NotSentinel(l))
  207.     {
  208.         count++;
  209.         l = l->GetNext();
  210.         ASSERT(l!=kODNULL,kODErrAssertionFailed);
  211.     }
  212.     return count;
  213. }
  214.  
  215. //------------------------------------------------------------------------------
  216. // LinkedList::Includes
  217. //
  218. // Does the list include a particular link?
  219. //------------------------------------------------------------------------------
  220.  
  221. ODBoolean LinkedList::Includes( const Link *link ) const
  222. {
  223.     Link* l = fSentinel.GetNext();
  224.     while (this->NotSentinel(l))
  225.     {
  226.         if( l == link )
  227.             return kODTrue;
  228.         else
  229.             l = l->GetNext();
  230.     }
  231.     return kODFalse;
  232. }
  233.  
  234. //------------------------------------------------------------------------------
  235. // LinkedList::DeleteAllLinks
  236. //
  237. // Description
  238. //------------------------------------------------------------------------------
  239.  
  240. void    LinkedList::DeleteAllLinks()
  241. {
  242.  
  243.     Link* l = fSentinel.GetNext();
  244.     Link* n = l;
  245.     while (this->NotSentinel(n))
  246.     {
  247.         n = l->GetNext();
  248.         delete l;    
  249.         l = n;
  250.     }
  251.     fSentinel.SetNext(&fSentinel);
  252.     fSentinel.SetPrevious(&fSentinel);
  253.     fSeed++;
  254. }
  255.  
  256. //------------------------------------------------------------------------------
  257. // LinkedList::RemoveAll
  258. //
  259. // Description
  260. //------------------------------------------------------------------------------
  261.  
  262. void    LinkedList::RemoveAll()
  263. {
  264.  
  265.     Link* l = fSentinel.GetNext();
  266.     Link* n = l;
  267.     while (this->NotSentinel(l))
  268.     {
  269.         n = l->GetNext();
  270.         l->SetNext(kODNULL);
  271.         l->SetPrevious(kODNULL);
  272.         l = n;
  273.     }
  274.     fSentinel.SetNext(&fSentinel);
  275.     fSentinel.SetPrevious(&fSentinel);
  276. }
  277.  
  278. //------------------------------------------------------------------------------
  279. // LinkedList::Remove
  280. //
  281. // Description
  282. //------------------------------------------------------------------------------
  283.  
  284. void    LinkedList::Remove(Link& aLink)
  285. {
  286.     fSeed++;
  287.     aLink.Remove();
  288. }
  289.  
  290. //------------------------------------------------------------------------------
  291. // LinkedList::RemoveFirst
  292. //
  293. // Description
  294. //------------------------------------------------------------------------------
  295.  
  296. Link* LinkedList::RemoveFirst()
  297. {
  298.     Link* old = fSentinel.GetNext();
  299.     if (this->NotSentinel(old))
  300.     {
  301.         fSeed++;
  302.         old->Remove();
  303.         return old;
  304.     }
  305.     else
  306.     {
  307.         return kODNULL;
  308.     }
  309. }
  310.  
  311. //------------------------------------------------------------------------------
  312. // LinkedList::RemoveLast
  313. //
  314. // Description
  315. //------------------------------------------------------------------------------
  316.  
  317. Link* LinkedList::RemoveLast()
  318. {
  319.     Link* old = fSentinel.GetPrevious();
  320.     if (this->NotSentinel(old))
  321.     {
  322.         fSeed++;
  323.         old->Remove();
  324.         return old;
  325.     }
  326.     else
  327.     {
  328.         return kODNULL;
  329.     }
  330. }
  331.  
  332. //------------------------------------------------------------------------------
  333. // LinkedList::AddFirst
  334. //
  335. // Description
  336. //------------------------------------------------------------------------------
  337.  
  338. void    LinkedList::AddFirst(Link* link)
  339. {
  340.     link->AddAfter(this->GetSentinel());
  341.     fSeed++;
  342. }
  343.  
  344. //------------------------------------------------------------------------------
  345. // LinkedList::AddLast( Link )
  346. //
  347. // Description
  348. //------------------------------------------------------------------------------
  349.  
  350. void    LinkedList::AddLast(Link* link)
  351. {
  352.     link->AddBefore(this->GetSentinel());
  353.     fSeed++;
  354. }
  355.  
  356. //------------------------------------------------------------------------------
  357. // LinkedList::AddLast( LinkedList )
  358. //
  359. // Append contents of another list to my end. (Other list becomes empty.)
  360. //------------------------------------------------------------------------------
  361.  
  362. void    LinkedList::AddLast( LinkedList &list )
  363. {
  364.     if( !list.IsEmpty() ) {
  365.         Link *myLast = fSentinel.GetPrevious();
  366.         Link *itsFirst = list.First();
  367.         myLast->SetNext(itsFirst);
  368.         itsFirst->SetPrevious(myLast);
  369.         
  370.         Link *itsLast = list.Last();
  371.         itsLast->SetNext(this->GetSentinel());
  372.         fSentinel.SetPrevious(itsLast);
  373.         
  374.         list.fSentinel.SetNext(this->GetSentinel());
  375.         list.fSentinel.SetPrevious(this->GetSentinel());
  376.  
  377.         fSeed++;
  378.         list.fSeed++;
  379.     }
  380. }
  381.  
  382. //------------------------------------------------------------------------------
  383. // LinkedList::AddLastUnique( LinkedList )
  384. //
  385. // Append contents of another list (w/o duplication) to my end.
  386. //------------------------------------------------------------------------------
  387.  
  388. void    LinkedList::AddLastUnique( LinkedList &list )
  389. {
  390.     for( Link *link = fSentinel.GetNext(); this->NotSentinel(link); link=link->GetNext() )
  391.         if( list.Includes(link) )
  392.             list.Remove(*link);
  393.     this->AddLast(list);
  394. }
  395.  
  396. //------------------------------------------------------------------------------
  397. // LinkedList::AddBefore
  398. //
  399. // Description
  400. //------------------------------------------------------------------------------
  401.  
  402. void LinkedList::AddBefore(Link& existing, Link* link)
  403. {
  404.     link->AddBefore(&existing);
  405.     fSeed++;
  406. }
  407.  
  408. //------------------------------------------------------------------------------
  409. // LinkedList::AddAfter
  410. //
  411. // Description
  412. //------------------------------------------------------------------------------
  413.  
  414. void LinkedList::AddAfter(Link& existing, Link* link)
  415. {
  416.     link->AddAfter(&existing);
  417.     fSeed++;
  418. }
  419.  
  420. //------------------------------------------------------------------------------
  421. // LinkedList::After
  422. //
  423. // Description
  424. //------------------------------------------------------------------------------
  425.  
  426. Link* LinkedList::After(const Link& link) const
  427. {
  428.     Link *next = link.GetNext();
  429.     if( this->IsSentinel(next) )
  430.         return kODNULL;
  431.     else
  432.         return next;
  433. }
  434.  
  435. //------------------------------------------------------------------------------
  436. // LinkedList::Before
  437. //
  438. // Description
  439. //------------------------------------------------------------------------------
  440.  
  441. Link* LinkedList::Before(const Link& link) const
  442. {
  443.     Link *prev = link.GetPrevious();
  444.     if( this->IsSentinel(prev) )
  445.         return kODNULL;
  446.     else
  447.         return prev;
  448. }
  449.  
  450. //------------------------------------------------------------------------------
  451. // LinkedList::First
  452. //
  453. // Description
  454. //------------------------------------------------------------------------------
  455.  
  456. Link*    LinkedList::First()  const
  457. {
  458.     return this->NotSentinel(fSentinel.GetNext()) ? fSentinel.GetNext() : (Link*) kODNULL;
  459. }
  460.  
  461. //------------------------------------------------------------------------------
  462. // LinkedList::Last
  463. //
  464. // Description
  465. //------------------------------------------------------------------------------
  466.  
  467. Link* LinkedList::Last() const
  468. {
  469.     return this->NotSentinel(fSentinel.GetPrevious()) ? fSentinel.GetPrevious() : (Link*) kODNULL;
  470. }
  471.  
  472.  
  473. //======================================================================================
  474. // Class LinkedListIterator
  475. //======================================================================================
  476.  
  477. //------------------------------------------------------------------------------
  478. // LinkedListIterator::LinkedListIterator
  479. //
  480. // Constructor for LinkedListIterator
  481. //------------------------------------------------------------------------------
  482.  
  483. LinkedListIterator::LinkedListIterator(LinkedList* list)
  484. {
  485.     fList = list;
  486.     fCurrent = kODNULL;
  487.     fNext = kODNULL;
  488.     fPrevious = kODNULL;
  489.     fSentinel = &list->fSentinel;
  490.     fSeed = fList->fSeed;    
  491. }
  492.  
  493. //------------------------------------------------------------------------------
  494. // LinkedListIterator::First
  495. //
  496. // Description
  497. //------------------------------------------------------------------------------
  498.  
  499. Link* LinkedListIterator::First()
  500. {
  501.     if (fList == kODNULL)
  502.         return kODNULL;
  503.         
  504.     if (fSeed != fList->fSeed)
  505.         THROW(kODErrIteratorOutOfSync);
  506.         
  507.     fCurrent = fList->First();
  508.     return fCurrent;
  509. }
  510.  
  511. //------------------------------------------------------------------------------
  512. // LinkedListIterator::Next
  513. //
  514. // Description
  515. //------------------------------------------------------------------------------
  516.  
  517. Link* LinkedListIterator::Next()
  518. {
  519.     if (fSeed != fList->fSeed)
  520.         THROW(kODErrIteratorOutOfSync);
  521.  
  522.     if (fCurrent == kODNULL)
  523.     {
  524.         if ((fNext == kODNULL) && (fPrevious == kODNULL))    // Just starting out
  525.         {
  526.             return this->First();
  527.         }
  528.         else    // Just deleted
  529.         {
  530.             fCurrent = fNext;
  531.             fPrevious = kODNULL;
  532.             fNext = kODNULL;
  533.         }
  534.     }
  535.     else
  536.         fCurrent = fCurrent->GetNext();
  537.     
  538.     if (fCurrent == fSentinel)
  539.         fCurrent = kODNULL;
  540.     return fCurrent;
  541. }
  542.  
  543. //------------------------------------------------------------------------------
  544. // LinkedListIterator::Last
  545. //
  546. // Description
  547. //------------------------------------------------------------------------------
  548.  
  549. Link* LinkedListIterator::Last()
  550. {
  551.     if (fList == kODNULL)
  552.         return kODNULL;
  553.  
  554.     if (fSeed != fList->fSeed)
  555.         THROW(kODErrIteratorOutOfSync);
  556.  
  557.     fCurrent = fList->Last();
  558.     return fCurrent;
  559. }
  560.  
  561. //------------------------------------------------------------------------------
  562. // LinkedListIterator::Previous
  563. //
  564. // Description
  565. //------------------------------------------------------------------------------
  566.  
  567. Link* LinkedListIterator::Previous()
  568. {
  569.     if (fList == kODNULL)
  570.         return kODNULL;
  571.  
  572.     if (fSeed != fList->fSeed)
  573.         THROW(kODErrIteratorOutOfSync);
  574.  
  575.     if (fCurrent == kODNULL)
  576.     {
  577.         if ((fNext == kODNULL) && (fPrevious == kODNULL))    // Just starting out
  578.         {
  579.             return this->Last();
  580.         }
  581.         else    // Just deleted
  582.         {
  583.             fCurrent = fPrevious;
  584.             fPrevious = kODNULL;
  585.             fNext = kODNULL;
  586.         }
  587.     }
  588.     else
  589.         fCurrent = fCurrent->GetPrevious();
  590.  
  591.     if (fCurrent == fSentinel)
  592.         fCurrent = kODNULL;
  593.     return fCurrent;
  594. }
  595.  
  596. //------------------------------------------------------------------------------
  597. // LinkedListIterator::RemoveCurrent
  598. //
  599. // Description
  600. //------------------------------------------------------------------------------
  601.  
  602. void  LinkedListIterator::RemoveCurrent()
  603. {
  604.     if (fList == kODNULL)
  605.         return;
  606.         
  607.     if (fSeed != fList->fSeed)
  608.         THROW(kODErrIteratorOutOfSync);
  609.          
  610.     if (fCurrent != kODNULL)
  611.     {
  612.         fNext = fCurrent->GetNext();
  613.         fPrevious = fCurrent->GetPrevious();
  614.             
  615.         fList->Remove(*fCurrent);
  616.         fCurrent = kODNULL;
  617.         fSeed = fList->fSeed;
  618.     }
  619. }
  620.